package com.slf.demo1;

import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvValidationException;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * 提取期货的主力合约数据
 */
public class FuturesDataExtractor1 {

    // 配置路径
    private static final String BASE_DIR = "F:\\BaiduNetdiskDownload\\指数高频\\期货\\2025期货";
    private static final String MASTER_SCHEDULE_DIR = BASE_DIR + "/主力时间表";
    private static final String SOURCE_DATA_DIR = BASE_DIR;
    private static final String TARGET_DIR = BASE_DIR + "/提取的数据";

    public static void main(String[] args) {
        // 确保目标目录存在
        createDirectoryIfNotExists(TARGET_DIR);

        try {
            // 处理所有期货品种
            processFuturesTypes();
            System.out.println("数据处理完成！");
        } catch (Exception e) {
            System.err.println("处理过程中发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private static void processFuturesTypes() throws IOException {
        File masterDir = new File(MASTER_SCHEDULE_DIR);
        File[] masterFiles = masterDir.listFiles((dir, name) -> name.endsWith(".csv"));

        if (masterFiles == null) {
            System.err.println("未找到主力时间表文件");
            return;
        }

        // 创建全局合约映射表
        Map<String, String> globalContractMap = new HashMap<>();

        // 第一步：读取所有主力时间表到全局映射表
        for (File masterFile : masterFiles) {
            String futuresType = FilenameUtils.getBaseName(masterFile.getName()).split("\\.")[0];
            System.out.println("读取期货品种主力时间表: " + futuresType);
            readMasterSchedule(globalContractMap, masterFile, futuresType);
        }

        // 第二步：处理每个品种的数据提取
        for (File masterFile : masterFiles) {
            String futuresType = FilenameUtils.getBaseName(masterFile.getName()).split("\\.")[0];
            System.out.println("处理期货品种: " + futuresType);
            extractDataForFuturesType(futuresType, globalContractMap);
        }
    }

    private static void readMasterSchedule(Map<String, String> globalMap, File masterFile, String futuresType) {
        try (CSVReader reader = new CSVReader(new FileReader(masterFile))) {
            // 跳过标题行
            reader.skip(1);

            String[] nextLine;
            while ((nextLine = reader.readNext()) != null) {
                if (nextLine.length >= 3) {
                    String tradeDate = nextLine[1];  // 交易日期
                    String contractCode = nextLine[2]; // 期货合约代码
                    // 使用新键格式：品种_日期
                    String key = futuresType + "_" + tradeDate;
                    globalMap.put(key, contractCode);
                }
            }
        } catch (IOException | CsvValidationException e) {
            System.err.println("读取主力时间表错误: " + e.getMessage());
        }
    }

    private static void extractDataForFuturesType(String futuresType, Map<String, String> globalContractMap) {
        String sourceTypeDir = SOURCE_DATA_DIR + "/" + futuresType;
        File typeDir = new File(sourceTypeDir);

        if (!typeDir.exists() || !typeDir.isDirectory()) {
            System.err.println("期货目录不存在: " + sourceTypeDir);
            return;
        }

        // 获取该品种目录下的所有ZIP文件
        File[] zipFiles = typeDir.listFiles((dir, name) -> name.endsWith(".zip"));
        if (zipFiles == null || zipFiles.length == 0) {
            System.err.println("未找到ZIP文件: " + sourceTypeDir);
            return;
        }

        for (File zipFile : zipFiles) {
            // 从文件名提取日期（去掉.zip后缀）
            String zipName = zipFile.getName();
            String tradeDate = zipName.substring(0, zipName.length() - 4);
            String key = futuresType + "_" + tradeDate;

            // 从全局映射表获取合约代码
            String contractCode = globalContractMap.get(key);
            if (contractCode == null) {
                System.err.println("未找到主力合约映射: " + key);
                continue;
            }
            //去除.CFX后缀
            contractCode = contractCode.substring(0, contractCode.indexOf("."));

            // 创建目标目录
            String targetDirPath = TARGET_DIR + "/" + futuresType + "/" + tradeDate;
            createDirectoryIfNotExists(targetDirPath);

            // 目标文件路径（使用合约代码.CFX后缀）
            String targetFilePath = targetDirPath + "/" + contractCode + ".csv";
            extractFromZip(zipFile, contractCode + ".csv", targetFilePath);
        }
    }

    private static void extractFromZip(File zipFile, String entryName, String targetPath) {
        try (ZipFile zip = new ZipFile(zipFile)) {
            Enumeration<ZipArchiveEntry> entries = zip.getEntries();

            while (entries.hasMoreElements()) {
                ZipArchiveEntry entry = entries.nextElement();
                if (entry.getName().equals(entryName)) {
                    try (InputStream in = zip.getInputStream(entry);
                         FileOutputStream out = new FileOutputStream(targetPath)) {
                        IOUtils.copy(in, out);
                        System.out.println("已提取: " + entryName + " -> " + targetPath);
                    }
                    return;
                }
            }
            System.err.println("未在ZIP中找到文件: " + entryName + " in " + zipFile.getName());
        } catch (IOException e) {
            System.err.println("解压ZIP文件错误: " + e.getMessage());
        }
    }

    private static void createDirectoryIfNotExists(String path) {
        try {
            Files.createDirectories(Paths.get(path));
        } catch (IOException e) {
            System.err.println("创建目录失败: " + path + " - " + e.getMessage());
        }
    }
}